package cn.edu.zut.sunday.config;

import static cn.edu.zut.sunday.constant.BaseConstant.BASE_PACKAGE_NAME;

import com.zaxxer.hikari.HikariDataSource;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Slf4j
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = BASE_PACKAGE_NAME)
@PropertySource(value = {"classpath:/jdbc.properties"})
public class DBConfig {

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Value("${hibernate.dialect}")
    private String dialect;

    @Value("${hibernate.show_sql}")
    private String showSQL;

    @Value("${hibernate.format_sql}")
    private String formatSQL;

    @Value("${hibernate.hbm2ddl.auto}")
    private String hbm2dll;


    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactory(@Autowired DataSource dataSource){
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setPackagesToScan(BASE_PACKAGE_NAME);
        entityManagerFactoryBean.setDataSource(dataSource);
        entityManagerFactoryBean.setPersistenceUnitName("ApplicationEntityManager");
        entityManagerFactoryBean.setPersistenceProvider(new HibernatePersistenceProvider());

        final HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
        entityManagerFactoryBean.setJpaVendorAdapter(hibernateJpaVendorAdapter);
        entityManagerFactoryBean.setJpaDialect(new HibernateJpaDialect());
        final Properties properties = getHibernateProperties();
        entityManagerFactoryBean.setJpaProperties(properties);

        return entityManagerFactoryBean;
    }

    private Properties getHibernateProperties() {
        final Properties properties = new Properties();
        // 设置运行相关配置
        properties.setProperty("hibernate.dialect", dialect);
        properties.setProperty("hibernate.show_sql", showSQL);
        properties.setProperty("hibernate.format_sql", formatSQL);
        properties.setProperty("hibernate.hbm2ddl.auto", hbm2dll);
        // 设置数据库连接配置
        properties.setProperty("hibernate.connection.driver", driver);
        properties.setProperty("hibernate.connection.url", url);
        properties.setProperty("hibernate.connection.username", username);
        properties.setProperty("hibernate.connection.password", password);
        properties.setProperty("hibernate.connection.provider_class",
          "com.zaxxer.hikari.hibernate.HikariConnectionProvider");
        return properties;
    }


    @Bean(name = "transactionManager")
    public JpaTransactionManager getTransactionManager(@Autowired EntityManagerFactory entityManagerFactoryBean){
        final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(entityManagerFactoryBean);

        log.info("txManager success!");
        return jpaTransactionManager;
    }

    @Bean
    public DataSource dataSource(){
        final HikariDataSource hikariDataSource = new HikariDataSource();

        hikariDataSource.setPassword(password);
        hikariDataSource.setUsername(username);
        hikariDataSource.setDriverClassName(driver);
        hikariDataSource.setJdbcUrl(url);
        hikariDataSource.setMaximumPoolSize(20);
        hikariDataSource.setConnectionTimeout(60000);
        hikariDataSource.setMinimumIdle(10);
        hikariDataSource.setIdleTimeout(500000);
        hikariDataSource.setMaxLifetime(540000);
        hikariDataSource.setConnectionTestQuery("SELECT 1");
        hikariDataSource.setPoolName("HikariCP-JavaEE");

        return hikariDataSource;
    }

}
